/*esp32-stm32 communication*/

#include "esc.h"

typedef struct {
  UART_HandleTypeDef *huart;
  uint32_t (*tickhook)(void);
  uint8_t status;
  uint16_t heartbeat_pkg_interval;
}esc_t;

typedef struct {
  char date[10];
  char time[5];
  double elec;
  uint8_t wifi;

  float temp;
  float humi;
  uint32_t smoke;
} esc_data_t;

static esc_t esc_setting;
static esc_data_t esc_data;

static void esc_tx_handler(void);
static void esc_rx_handler(void);

void esc_init(UART_HandleTypeDef *huart, uint32_t (*tickhook)(void))
{
  esc_setting.huart    = huart;
  esc_setting.tickhook = tickhook;
  esc_setting.status   = STATUS_RUN;
  esc_setting.heartbeat_pkg_interval = 600;//10*600=1min
  /*smoke data*/
  HAL_ADC_Start(&hadc1);
  if (HAL_OK == HAL_ADC_PollForConversion(&hadc1, 1)) {
    esc_data.smoke = HAL_ADC_GetValue(&hadc1);
  }

  /*aht30 data*/
  for (uint8_t i = 0; i < 3; i++) {
    if (aht30_readdata(&esc_data.humi, &esc_data.temp)) break;
  }

  /*get esp32 data*/
  cJSON *json = NULL, *json_content = NULL;
  json         = cJSON_CreateObject();
  json_content = cJSON_CreateObject();
  if (json == NULL || json_content == NULL)
    while (1);
  cJSON_AddNumberToObject(json, "status", HEARTBEAT);
  cJSON_AddItemToObject(json, "content", json_content);
  cJSON_AddNumberToObject(json_content, "smoke", esc_data.smoke);
  cJSON_AddNumberToObject(json_content, "temp", esc_data.temp);
  cJSON_AddNumberToObject(json_content, "humi", esc_data.humi);
  ESC_PRINTF(esc_setting.huart, "%s\n", cJSON_PrintUnformatted(json));
  cJSON_Delete(json_content);
  cJSON_Delete(json);
  HAL_Delay(20);

  esc_rx_handler();
}

uint8_t esc_add_strike(esc_pkg_t type)
{
  //todo
  return 0;
}

void esc_handler(void)
{
  // 处理接收
  esc_rx_handler();

  // 发送心跳包或突发包(每隔2s)
  esc_tx_handler();
}

static void esc_tx_handler(void)
{
  static uint32_t last_tick = 0;
  uint32_t current_tick     = esc_setting.tickhook();
  static uint16_t heartbeat_pkg_tick = 0;

  if (esc_setting.status == STATUS_PAUSE) return;

  /*心跳间隔为10ms*/
  if (current_tick - last_tick <= 10) return;
  last_tick = current_tick;

  /*突发包部分*/
    //todo
  /**/

  /*心跳包部分(1min一次)*/
  heartbeat_pkg_tick++;
  if (heartbeat_pkg_tick < esc_setting.heartbeat_pkg_interval) return;
  heartbeat_pkg_tick = 0;

  /*sent heartbeat pkg*/
  cJSON *json = NULL, *json_content = NULL;
  json         = cJSON_CreateObject();
  json_content = cJSON_CreateObject();
  if (json == NULL || json_content == NULL)
    while (1);
  cJSON_AddNumberToObject(json, "status", HEARTBEAT);
  cJSON_AddItemToObject(json, "content", json_content);
  cJSON_AddNumberToObject(json_content, "smoke", esc_data.smoke);
  cJSON_AddNumberToObject(json_content, "temp", esc_data.temp);
  cJSON_AddNumberToObject(json_content, "humi", esc_data.humi);
  ESC_PRINTF(esc_setting.huart, "%s\n", cJSON_PrintUnformatted(json));
  cJSON_Delete(json_content);
  cJSON_Delete(json);

}

static void esc_rx_handler(void)
{
  cJSON *json = NULL, *json_content = NULL;
  uint16_t status = 0;

  /*检查串口是否收到数据*/
  if (!ESC_Get_recState(esc_setting.huart)) return;
  char *data = ESC_ReturnRxData(esc_setting.huart);

  if ((json = cJSON_Parse(data)) == NULL) return; // 将读到的字符串解析为json对象
  /*获取键status的值*/
  if ((status = cJSON_GetNumberValue(cJSON_GetObjectItem(json, "status"))) == NAN) {
    cJSON_Delete(json);
    return;
  }

  if (status == STATUS_PAUSE)
    esc_setting.status = STATUS_PAUSE;
  else
    esc_setting.status = STATUS_RUN;

  switch (status) {
    case HEARTBEAT: {
      json_content = cJSON_GetObjectItem(json, "content");
      if (json_content == NULL) break;
      /*elec*/
      if (cJSON_IsNumber(cJSON_GetObjectItem(json_content, "elec"))) {
        esc_data.elec = cJSON_GetObjectItem(json_content, "elec")->valuedouble;
      }
      /*date*/
      if (cJSON_IsString(cJSON_GetObjectItem(json_content, "date"))) {
        strcpy(esc_data.date, (const char *)cJSON_GetObjectItem(json_content, "date")->valuestring);
      }
      /*time*/
      if (cJSON_IsString(cJSON_GetObjectItem(json_content, "time"))) {
        strcpy(esc_data.time, (const char *)cJSON_GetObjectItem(json_content, "time")->valuestring);
      }
      /*wifi*/
      if (cJSON_IsNumber(cJSON_GetObjectItem(json_content, "wifi"))) {
        esc_data.wifi = (uint8_t)cJSON_GetObjectItem(json_content, "wifi")->valueint;
      }
      cJSON_Delete(json_content);
      break;
    }
    default: {
      break;
    }
  }

  cJSON_Delete(json);
}
